﻿using MyAlbum.Services;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System;
using System.Linq;
using MyAlbum.Model;
using PersonalAlbum.Exceptions;
namespace UnitTests
{


    /// <summary>
    ///This is a test class for ReplyServiceTest and is intended
    ///to contain all ReplyServiceTest Unit Tests
    ///</summary>
    [TestClass()]
    public class ReplyServiceTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        [TestInitialize()]
        public void MyTestInitialize()
        {
            _testConfig = new TestConfig();
            _testConfig.Initialize(PersistenceModes.Xml);
            replies = new List<MyAlbum.Model.Reply>();
            entries = new List<Entry>();
        }
        //
        //Use TestCleanup to run code after each test has run
        [TestCleanup()]
        public void MyTestCleanup()
        {
            foreach (var item in replies)
            {
                Service.DeleteItem(item);
            }
            _testConfig.Dispose();
            foreach (var item in entries)
            {
                EntryService.DeleteItem(item);
            }
        }
        //
        #endregion
        private TestConfig _testConfig;
        private List<MyAlbum.Model.Reply> replies;
        MyAlbum.Services.ReplyService Service
        {
            get
            {
                return ObjectFactory.GetInstance<IDataService<MyAlbum.Model.Reply>>() as MyAlbum.Services.ReplyService;
            }
        }

        private List<MyAlbum.Model.Entry> entries;
        MyAlbum.Services.EntryService EntryService
        {
            get
            {
                return ObjectFactory.GetInstance<IEntryService>() as EntryService;
            }
        }

        /// <summary>
        ///A test for UpdateItem
        ///</summary>
        [TestMethod()]
        public void UpdateItemTest()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                EntryId = new Random().Next(),
                Body = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                UserName = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow
            };
            target.AddItem(item, new MyAlbum.Utility.GenericValidationSummary());
            this.replies.Add(item);
            var loaded = target.GetItems().SingleOrDefault(i => i.Id == item.Id);
            Assert.IsNotNull(loaded);
            Compare(item, loaded);
            item.IsApproved = true;
            target.UpdateItem(item, new MyAlbum.Utility.GenericValidationSummary());
            loaded = target.GetItems().SingleOrDefault(i => i.Id == item.Id);
            Assert.IsNotNull(loaded);
            Compare(item, loaded);
        }

        /// <summary>
        ///A test for GetItems
        ///</summary>
        [TestMethod()]
        public void GetItemsTest()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                EntryId = new Random().Next(),
                Body = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                UserName = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow
            };
            target.AddItem(item, new MyAlbum.Utility.GenericValidationSummary());
            this.replies.Add(item);
            var loaded = target.GetItems().SingleOrDefault(i => i.Id == item.Id);
            Assert.IsNotNull(loaded);
            Compare(item, loaded);
        }

        /// <summary>
        ///A test for GetItemById
        ///</summary>
        [TestMethod()]
        public void GetItemByIdTest()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                EntryId = new Random().Next(),
                Body = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                UserName = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow
            };
            target.AddItem(item, new MyAlbum.Utility.GenericValidationSummary());
            this.replies.Add(item);
            var loaded = target.GetItemById(item.Id);
            Assert.IsNotNull(loaded);
            Compare(item, loaded);
        }

        /// <summary>
        ///A test for GetItemById
        ///</summary>
        [TestMethod()]
        public void GetItemByIdTest_Bad_ID()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                EntryId = new Random().Next(),
                Body = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                UserName = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow
            };
            target.AddItem(item, new MyAlbum.Utility.GenericValidationSummary());
            this.replies.Add(item);
            var loaded = target.GetItemById(item.Id + 1);
            Assert.IsNull(loaded);
        }
        /// <summary>
        ///A test for DeleteItem
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(AssertionException))]
        public void DeleteItem_Null_Item()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            target.DeleteItem(null);

        }

        /// <summary>
        ///A test for DeleteItem
        ///</summary>
        [TestMethod()]
        public void DeleteItemTest()
        {
            var user = new GenericUser("tal", new string[] { "Admin" });
            ((TestUser)ObjectFactory.GetInstance<IUser>()).SetUser(user);
            Entry e = EntryServiceTest.Create();
            EntryService.AddItem(e, new MyAlbum.Utility.GenericValidationSummary());
            this.entries.Add(e);
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                EntryId = e.Id,
                Body = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                UserName = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow
            };
            target.AddItem(item, new MyAlbum.Utility.GenericValidationSummary());
            this.replies.Add(item);
         
            var entry = EntryService.GetItemById(e.Id);
            Assert.IsNotNull(entry);
            Assert.IsNotNull(entry.Replies);
            var reply = entry.Replies.SingleOrDefault(r => r.Id == item.Id);
            Assert.IsNotNull(reply);
            target.DeleteItem(item);
            entry = EntryService.GetItemById(e.Id);
            Assert.IsNotNull(entry);
            Assert.IsNotNull(entry.Replies);
            reply = entry.Replies.SingleOrDefault(r => r.Id == item.Id);
            Assert.IsNull(reply);
        }

        /// <summary>
        ///A test for ReplyService Constructor
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ReplyServiceConstructorTest()
        {
            MyAlbum.Data.IRepository<MyAlbum.Model.Reply> replyRepository = null;
            MyAlbum.Services.ReplyService target = new MyAlbum.Services.ReplyService(replyRepository);
        }

        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]
        public void AddItemTest()
        {
            var user = new GenericUser("tal", new string[] { "Admin" });
            ((TestUser)ObjectFactory.GetInstance<IUser>()).SetUser(user);
            Entry e = EntryServiceTest.Create();
            EntryService.AddItem(e, new MyAlbum.Utility.GenericValidationSummary());
            this.entries.Add(e);
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                EntryId = e.Id,
                Body = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                UserName = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow
            };
            target.AddItem(item, new MyAlbum.Utility.GenericValidationSummary());
            this.replies.Add(item);
            
            var entry = EntryService.GetItemById(e.Id);
            Assert.IsNotNull(entry);
            Assert.IsNotNull(entry.Replies);
            var reply = entry.Replies.SingleOrDefault(r => r.Id == item.Id);
            Assert.IsNotNull(reply);
            Compare(item, reply);
        }

        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]       
        public void AddItem_Null_Subject()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                Body = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                UserName = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow,
                EntryId = new Random().Next()

            };
            var v = new MyAlbum.Utility.GenericValidationSummary();
            target.AddItem(item, v);
            this.replies.Add(item);
            Assert.IsFalse(v.IsValid);
            Assert.AreEqual("Subject", v.Errors.Keys.First());
        }

        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]       
        public void AddItem_Empty_Subject()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                Subject = "",
                Body = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                UserName = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow,
                EntryId = new Random().Next()

            };
            var v = new MyAlbum.Utility.GenericValidationSummary();
            target.AddItem(item, v);
            this.replies.Add(item);
            Assert.IsFalse(v.IsValid);
            Assert.AreEqual("Subject", v.Errors.Keys.First());
        }

        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]       
        public void AddItem_Null_UserName()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                Body = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow,
                EntryId = new Random().Next()

            };
            var v = new MyAlbum.Utility.GenericValidationSummary();
            target.AddItem(item, v);
            this.replies.Add(item);
            Assert.IsFalse(v.IsValid);
            Assert.AreEqual("UserName", v.Errors.Keys.First());
        }

        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]
        public void AddItem_Empty_UserName()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                UserName = "",
                Body = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow,
                EntryId = new Random().Next()

            };
            var v = new MyAlbum.Utility.GenericValidationSummary();
            target.AddItem(item, v);
            this.replies.Add(item);
            Assert.IsFalse(v.IsValid);
            Assert.AreEqual("UserName", v.Errors.Keys.First());
        }

        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]
        public void AddItem_Null_Body()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                UserName = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow,
                EntryId = new Random().Next()

            };
            target.AddItem(item, new MyAlbum.Utility.GenericValidationSummary());
            this.replies.Add(item);
        }

        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]
        public void AddItem_Empty_Body()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                Body = "",
                UserName = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow,
                EntryId = new Random().Next()

            };
            target.AddItem(item, new MyAlbum.Utility.GenericValidationSummary());
            this.replies.Add(item);
        }

        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]
        public void AddItem_Zero_Entry_ID()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                Body = "",
                UserName = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow
            };
            var v = new MyAlbum.Utility.GenericValidationSummary();
            target.AddItem(item,v);
            this.replies.Add(item);
            Assert.IsFalse(v.IsValid);
            Assert.AreEqual("EntryId", v.Errors.Keys.First());
        }


        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(AssertionException))]
        public void AddItem_Null_Item()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            target.AddItem(null, new MyAlbum.Utility.GenericValidationSummary());
        }

        private void Compare(Reply expected, Reply actual)
        {
            Assert.AreEqual(expected.Body, actual.Body);
            Assert.AreEqual(expected.Email, actual.Email);
            Assert.AreEqual(expected.EntryId, actual.EntryId);
            Assert.AreEqual(expected.Id, actual.Id);
            Assert.AreEqual(expected.IsApproved, actual.IsApproved);
            Assert.AreEqual(expected.Subject, actual.Subject);
            //will not work with sql:
            Assert.AreEqual(expected.TimeStamp, actual.TimeStamp);
            Assert.AreEqual(expected.UserName, actual.UserName);
        }



        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]
        public void UpdateItem_Null_Subject()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                Body = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                UserName = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow,
                EntryId = new Random().Next()

            };
            target.UpdateItem(item, new MyAlbum.Utility.GenericValidationSummary());
            this.replies.Add(item);
        }

        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]
        public void UpdateItem_Empty_Subject()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                Subject = "",
                Body = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                UserName = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow,
                EntryId = new Random().Next()

            };
            target.UpdateItem(item, new MyAlbum.Utility.GenericValidationSummary());
            this.replies.Add(item);
        }

        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]
        public void UpdateItem_Null_UserName()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                Body = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow,
                EntryId = new Random().Next()

            };
            var v = new MyAlbum.Utility.GenericValidationSummary();
            target.UpdateItem(item,v);
            this.replies.Add(item);
        }

        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]
        public void UpdateItem_Empty_UserName()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                UserName = "",
                Body = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow,
                EntryId = new Random().Next()

            };
            var v = new MyAlbum.Utility.GenericValidationSummary();
            target.UpdateItem(item, v);
            this.replies.Add(item);
        }

        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]
        public void UpdateItem_Null_Body()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                UserName = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                EntryId=new Random().Next(),
                
                TimeStamp = DateTime.UtcNow
            };
            var v = new MyAlbum.Utility.GenericValidationSummary();
            target.UpdateItem(item, v);
            this.replies.Add(item);
        }

        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]      
        public void UpdateItem_Empty_Body()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                Body = "",
                UserName = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow,
                Id = new Random().Next(),
                EntryId = new Random().Next()

            };
            var v = new MyAlbum.Utility.GenericValidationSummary();
            target.UpdateItem(item, v);
            this.replies.Add(item);
        }

      

        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]
        public void UpdateItem_Zero_Entry_ID()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            MyAlbum.Model.Reply item = new Reply()
            {
                Body = "aaa",
                UserName = Guid.NewGuid().ToString(),
                Email = Guid.NewGuid().ToString(),
                Subject = Guid.NewGuid().ToString(),
                TimeStamp = DateTime.UtcNow,
                Id = new Random().Next()
            };
            var v = new MyAlbum.Utility.GenericValidationSummary();
            target.UpdateItem(item,v);
            this.replies.Add(item);
            Assert.IsFalse(v.IsValid);
            Assert.AreEqual("EntryId", v.Errors.Keys.First());
        }


        /// <summary>
        ///A test for AddItem
        ///</summary>
        [TestMethod()]
        [ExpectedException(typeof(AssertionException))]
        public void UpdateItem_Null_Item()
        {
            MyAlbum.Services.ReplyService target = this.Service;
            target.UpdateItem(null, new MyAlbum.Utility.GenericValidationSummary());
        }
    }
}
